#!/usr/bin/perl

# ---------- Init variables -------
#my $version = "0.0001";
# ---------- external readable parameters -------
## Functions
##-------------------------------------------------------
#
# stict syntax checking.
require Exporter;
use SIM_settings;
use SIM_cgiSettings;
use SIM_base;
use SIM_cgi;
use SIM_nodeInfo;
use CGI qw(param);
use SNMP_util;
use strict;

my $tool = $ARGV[0];
my $action = $ARGV[1];
my $device = $ARGV[2];
my $option1 = $ARGV[3];
my $option2 = $ARGV[4];
my $option3 = $ARGV[5];
my $option4 = $ARGV[6];

if ( $device eq "none" ) {
  $device = "";
}

my $baseUrl = "$httpScriptName?$tool";
my $cachFile = "$SIMparam{'SIMtmpDir'}/switchIpList";

# ----------------- subs ---------------------

sub listSwitches {
  # list all switches and display sthe status color (allowing to select an device)
  my $workDir = $SIMparam{'SIMswitchDevices'};
  if ( ! -d $workDir ) {
    print("<H2>Oops, SIMswitchDevices not found.");
  } else {
    open( SWITCH, ">$cachFile.$$") || die("Oops, could not create $cachFile.$$");;
    chdir $workDir;
    print("<TABLE><TR>");
    my @devices = <*>;
    my $num = 0;
    foreach my $entry (@devices) {
      printDebug(1, "listSwitches: entry = $entry. ");
      if ( ! -f "$entry/switchip" ) {
        print("<TD BGCOLOR=#EEEEEE>$entry<TD>");
        system(" rm -fr $workDir/$entry ");
        $num++;
      } else {
        my $switchIpInfo = catFileLine("$entry/switchip");
        my ( $ipAddr, $rest ) = split(' ', $switchIpInfo);
        print SWITCH ("$ipAddr\n");
        my $statusColor = testNodeStatus( $ipAddr );
        print("<TD BGCOLOR=$statusColor ALIGN=center><A HREF=$httpScriptName?$tool+displaySwitch+$entry>$entry</A></TD>");
        $num++;
        if ( $num > 9 ) {
          $num = 0;
          print("</TR><TR>");
        }
      }
    }
    print("</TR></TABLE>");
    close SWITCH;
    system(" mv $cachFile.$$ $cachFile ");
  }
}

sub testMacIp {
  # test if an mac has an current ip entry
  my $testMac = "@_[0]";
  my @ipList = <$SIMparam{'SIMmacDatab'}/$testMac/*-ipaddr-*>;
  my %sortList = ();
  foreach my $entry (@ipList) {
    my $timeStamp = (stat($entry))[9];
    if ( $sortList{$timeStamp} eq "" ) {
      $sortList{$timeStamp} = $entry;
    }
  }
  my $last;
  foreach my $key ( sort keys %sortList ) {
#   print("<TR><TD COLSPAN=99>testMacIp: key = $key, value = $sortList{$key}</TD></TR>");
    my $testIp = catFileLine($sortList{$key});
    my ( $getMac, $getColor ) = getMacAddr($testIp);
    if ( $testMac eq $getMac ) {
      $last = $testIp;
    } else {
       unlink($sortList{$key});
    }
  }
# print("<TR><TD COLSPAN=99>testMacIp: last = $last. ");
  return $last;
}

sub switchMenu {
  my $devName = "@_[0]";
# print("<TABLE WIDTH=100% BGCOLOR=#DDDDDD><TR><TD ALIGN=center>");
  printEntry2("List","list all nodes", "$tool+$action", "$tool+none", "", "line", "Action:", "");
  if ( -f $cachFile ) {
    printEntry2("Location","list the switches location info", "$tool+$action", "mon+listCache", "switchIpList+switchLocation", "line", "|", "");
  }
  if ( $devName ne "" ) {
    printEntry2("$devName","display the device", "$tool+$action+$device", "$tool+displaySwitch+$devName", "", "line", "|", "");
    printEntry2("poll switch","poll the switch table", "$tool+$action+$device", "$tool+pollSwitch+$devName", "", "line", "|", "");
  }
# print("</TD></TR></TABLE>");
}

sub pollSwitch {
  my $devName = "@_[0]";
  my $switchIpInfo = catFileLine("$SIMparam{'SIMswitchDevices'}/$devName/switchip");
  my ( $ipAddr, $community ) = split(' ', $switchIpInfo);
  if ( $ipAddr eq "" ) {
    print("<H2>Oops, no ip info found for $devName</H2>");
  } else {
    print("Polling $ipAddr<HR></CENTER><PRE>");
    system(" $SIMparam{'SIMswitchinfo'} node $ipAddr ");
    print("</PRE>");
  }
}

sub displaySwitch {
  # SNMP settings to prevent error logging.
  $SNMP_Session::suppress_warnings = 1000;

  my $devName = "@_[0]";
  my $dot1x;
  my $workDir = "$SIMparam{'SIMswitchDevices'}/$devName";
  if ( -f "$workDir/dot1x" ) {
    $dot1x = "yes";
  }
  if ( $devName eq "" ) {
    print("<H2>displaySwitch: Oops, no devicename selected.");
  } elsif ( ! -f "$workDir/switchip" ) {
    print("<H2>displaySwitch: Oops, devicename \"$devName\" not valid.");
  } elsif ( ! -r "$workDir/switchip" ) {
    print("<H2>displaySwitch: Oops, devicename \"$devName\" not readable.");
  } else {
    my $switchIpInfo = catFileLine("$workDir/switchip");
    my ( $ipAddr, $community ) = split(' ', $switchIpInfo);
    my $ipDir = getIpDir($ipAddr);
    my $firstMac = catFileLine("$ipDir/firstmac.txt");
    my $snmpLoc = catFileLine("$SIMparam{'SIMmacDatab'}/$firstMac/snmpLocation");
    if ( $snmpLoc ne "" ) {
      $snmpLoc = "( $snmpLoc )";
    }
    printDebug(1, "displaySwitch: ipAddr = $ipAddr, community = $community.");
    print("<P><FONT SIZE=+2><A HREF=$httpScriptName?mon+nodestatus+$ipAddr>$devName</A></FONT> $snmpLoc<P>");
    my $SNMPSTR = $community . "@" . $ipAddr . ":::::" . "1";
    printDebug(1, "displaySwitch: SNMPSTR = $SNMPSTR.");    
    my %macVlan = ();
    my %intInfo = ();
    # read all mac info
    my @macList = <$workDir/mac-*>;
    foreach my $entry (@macList) {
      printDebug(1, "displaySwitch: entry = $entry.");
      my $macEntry = catFileLine($entry);
      my ( $switchName, $mibInt, $macAddr, $date, $vlanNum, $vlanName, $intName ) = split(' ', $macEntry);
      $macVlan{$macAddr} = $vlanNum;
      $intInfo{$intName} = "$intInfo{$intName} $macAddr";
    }
    open( IN, "$workDir/interface-info");
    my @intInfo = <IN>;
    close IN;
    #$ShostName $MIB2INT[$BPORT] $HMAC $date $vlanNum $vlanName $intName{$mib2Int}
    printDebug(1, "displaySwitch: start table<BR>.");
    my $tableHeader = "<TR ALIGN=center BGCOLOR=#AAAAFF>
          <TD>Interface</TD>
          <TD>Vlan</TD>
          <TD COLSPAN=2>Subnet</TD>
          <TD>IP address</TD>
          <TD>Mac address</TD>
          <TD COLSPAN=2>Type</TD>
          <TD>Status</TD>
          <TD>DNS name</TD>
          <TD>Node name</TD>
          <TD>Dev type</TD>
          <TD>Int</TD>
          <TD>Switchport / description</TD>
        </TR>";
    print("<TABLE>$tableHeader");
    foreach my $line (@intInfo) {
      my ( $dot1xInfo, $operVlan, $userName, $bgColorInt );
      my ( $intNo, $intName, $intDescr ) = split(' ', $line, 3);
      my $operStatus = &snmpget("$SNMPSTR", ".1.3.6.1.2.1.2.2.1.8.$intNo");
      my $bgColor;
      if ( $operStatus eq "1" ) {
          $bgColor = $intStatusColor{'up'};
          if ( $dot1x eq "yes" ) {
            $operVlan = &snmpget("$SNMPSTR", "1.3.6.1.4.1.9.9.220.1.1.1.7.$intNo");
            $userName = &snmpget("$SNMPSTR", "1.3.6.1.4.1.9.9.220.1.11.1.4.$intNo");
          }
      } else {
        my $adminStatus = &snmpget("$SNMPSTR", ".1.3.6.1.2.1.2.2.1.7.$intNo");
        if ( $adminStatus eq "2" ) {
          $bgColor = $intStatusColor{'shut'};
        } elsif ( $adminStatus eq "1" ) {
          $bgColor = $intStatusColor{'down'};
        } else {
          $bgColor = $intStatusColor{'undefined'};
        }
      }
      if ( $userName ne "" ) {
        $userName = "$userName, ";
      }
      my $isTrunk;
      my $formatIntName = formatIntName($intName);
      my $trunkInfo = catFileLine("$workDir/trunk-$formatIntName");
#     if ( -f "$workDir/trunk-$formatIntName" ) {
      if ( $trunkInfo ne "" ) {
        $bgColorInt = "#AAAAAA";
        $isTrunk = "yes";
      } else {
        $bgColorInt = "#EEEEEE";
      }
      my ( $trunkInt, $trunkRest ) = split(' ', $trunkInfo, 2);
      my ( $intSpeed, $dIntSpeed ) = getDispIntSpeed($ipAddr, $SNMPSTR, $intNo, $intName);
      print("<TR BGCOLOR=$bgColorInt><TD BGCOLOR=$bgColor>$intName</TD><TD ALIGN=right>$operVlan</TD><TD COLSPAN=11>$userName $intDescr</TD><TD>$dIntSpeed $trunkRest</TD></TR>");
      my @intMacs = split(' ', $intInfo{$intName});
      foreach my $entry (@intMacs) {
        if ( $entry ne "" ) {
          if ( $isTrunk eq "yes" ) {
            # remove all switchport definitions, if an mac is on an trunk.
            if ( -f "$workDir/mac-$entry-$formatIntName" ) {
              unlink("$workDir/mac-$entry-$formatIntName");
              my $macFile = "$SIMparam{'SIMmacDatab'}/$entry/switchport-$devName-$formatIntName";
              if ( -f $macFile ) {
                unlink($macFile);
              }
              # use this line to monitor the cleanup process.
#             print("<TR><TD COLSPAN=99>$workDir/mac-$entry-$formatIntName $macFile</TD></TR>");        
            }
          } else {
            my $ipAddr = &testMacIp($entry);
            my $info;
            if ( $ipAddr ne "" ) {
              $info = printNodeLine( $ipAddr, "return" ); 
            } else {
              $info = "<TD></TD><TD></TD><TD></TD><TD COLSPAN=99>$entry</TD>";
            }
            print("<TR><TD></TD><TD ALIGN=right>$macVlan{$entry}</TD>$info</TR>");
          }
        }
#       sleep 1;
      }
    }
    printDebug(1, "displaySwitch: stop table<BR>.");
    print("$tableHeader</TABLE>");
  }
}

# ----------------- main ---------------------
# menu stuff
#&printMainMenu("line");
&switchMenu($device);
print("</TR></TABLE><CENTER>");

if ( $action eq "displaySwitch" ) {
  &displaySwitch($device);
} elsif ( $action eq "pollSwitch" ) {
  &pollSwitch($device);
} else {
  &listSwitches;
}
